package Bondarenko.algorithm.gen;

//FRUITFUL, MULTIPLAY AND MUTATE!!!

import java.util.List;
import java.util.Collections;  
import java.util.ArrayList; 

import Bondarenko.algorithm.calc.RandomStringOperation;


public class GACrossingString {

public static final int POPULATION_SIZE = 1000;
public static final double ELITE_RATE = 0.1;
public static final double SURVIVE_RATE = 0.5;
public static final double MUTATION_RATE = 0.2;
public static int TARGET;
private static final int MAX_ITER = 17;
public static  int SIZE;
public static int[] ARRAY = new int[SIZE];



void initializePopulation(List<Genome> population) {
	int tsize = SIZE-1;


for (int i=0; i<POPULATION_SIZE; i++) {
	StringBuilder str = new StringBuilder();
	for (int j = 0; j < tsize; j++) {
		
		str.append(RandomStringOperation.randStrOp());
	}
  // System.out.println(str);
	
	Genome citizen = new Genome(str.toString());
	
	population.add(citizen);
}

}

String mutate(String str) {
	int tsize = SIZE-1;
	int ipos = (int) (Math.random() * tsize);
	char delta = RandomStringOperation.randStrOp();
	//System.out.println(str);
	return str.substring(0, ipos) + delta + str.substring(ipos + 1);
}



List<Genome> mate(List<Genome> population) {
	int esize = (int) (POPULATION_SIZE * ELITE_RATE);
	int tsize = SIZE-1;
	List<Genome> children = new ArrayList<Genome>();
	
	selectElite(population, children, esize);
	
	for (int i = esize; i < POPULATION_SIZE * SURVIVE_RATE; i++) {
			int i1 = (int) (Math.random() * POPULATION_SIZE*SURVIVE_RATE);
			int i2 = (int) (Math.random() * POPULATION_SIZE*SURVIVE_RATE);
			int spos = (int) (Math.random() * tsize);
			
			String str = population.get(i1).str.substring(0, spos) +
			     population.get(i2).str.substring(spos);
			//System.out.println(str);
			if (Math.random() < MUTATION_RATE) {
				str = mutate(str);
			}
			Genome child = new Genome(str);
			children.add(child);
			
            }
     
     

     
     return children;
  }
     
     private void selectElite(List<Genome> population, List<Genome> children, int esize) {
    	 for (int i=0; i<esize; i++) {
    		 children.add(population.get(i));
    	 }
     }
     
     public void go() {
    	 List<Genome> population = new ArrayList<Genome>();
    	 initializePopulation(population);
    	 
    	 for (int i=0; i<MAX_ITER; i++) {
    		 Collections.sort(population);
    		
    		 System.out.println(i+": "+population.get(0));
    		 if (population.get(0).fitness == 0) {
    			 break;
    		 }
	 
    		 population = mate(population);
    	 }
    	 
     }
}		